package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;

import javax.jws.Oneway;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import engine.Cocomo;
import engine.Logger;
import engine.Project;
import engine.Ranges;
import engine.Similarity;
import engine.ARFFReader.ProjectPropertyDescriptor;
import engine.Project.ProjectProperty;

public class CompareWindow extends JFrame {

	private JPanel panel;
	private HashMap<String, ButtonGroup> properties;
	private ArrayList<Project> oldProjects;
	private ArrayList<ProjectPropertyDescriptor> characteristics;
	private JTextField locInput;
	private final Color light = Color.WHITE;
	private final Color dark = new Color(100,100,200);
	private ButtonGroup projectType;

	public CompareWindow(ArrayList<Project> oldProjects,
			ArrayList<ProjectPropertyDescriptor> characteristics) {
		panel = new JPanel();

		this.oldProjects = oldProjects;
		properties = new HashMap<String, ButtonGroup>();
		this.characteristics = characteristics;
		FlowLayout f = (FlowLayout) panel.getLayout();
		f.setVgap(0);
		add(panel);
		panel.setBackground(light);
		panel.setPreferredSize(new Dimension(700, 900));
		super.setTitle("Project Parameters");
		addRangeLabels();

		for (ProjectPropertyDescriptor descriptor : characteristics) {
			addLowHighSelection(descriptor.getName(), descriptor.getValues());
		}

		locInput = addTextInput("KLOC");
		projectType = addProjectTypeSelect("Project Type");	
		
		addLaunchButton();

		setVisible(true);
		pack();
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
	}

	private ButtonGroup addProjectTypeSelect(String string) {
		JPanel container = makeContainer();
		container.setPreferredSize(new Dimension(600, 65));
		container.setBackground(light);
		container.setBorder(BorderFactory.createLineBorder(dark));
//		FlowLayout flow = (FlowLayout)container.getLayout();
//		flow.setVgap(1);
		panel.add(container);
		
		ButtonGroup radio = new ButtonGroup();
		
		JLabel headLine = new JLabel("Chose Project Type");
		headLine.setPreferredSize(new Dimension(590,15));
		headLine.setForeground(dark);
		headLine.setHorizontalAlignment(JLabel.CENTER);
		container.add(headLine);
		container.add(makeLabeledRadioButtonField("Organic", radio));
		container.add(makeLabeledRadioButtonField("Semi-Detached", radio));
		container.add(makeLabeledRadioButtonField("Embedded", radio));
	
		return radio;
	}
	
	private JPanel makeLabeledRadioButtonField(String name, ButtonGroup group){
		JLabel label = new JLabel(name);
		label.setForeground(dark);
		JRadioButton type = makeRadio(name);
		type.setBackground(light);
		JPanel container = new JPanel();
		group.add(type);
		FlowLayout flow = (FlowLayout)container.getLayout();
		flow.setVgap(1);
		container.setPreferredSize(new Dimension(190,35));
		container.setBackground(light);
		container.add(label);
		container.add(type);
		return container;
		
	}

	private void addRangeLabels() {
		JPanel container = makeContainer();
		container.setBackground(dark);

		panel.add(container);
		JLabel rangeLabel = new JLabel(
				"Very Low - Low - Nominal - High - Very High - Extra High");
		rangeLabel.setForeground(light);

		container.add(rangeLabel);
	}

	private JPanel makeContainer() {
		JPanel container = new JPanel();
		container.setPreferredSize(new Dimension(600, 45));
		container.setBackground(light);
		return container;
	}

	private JTextField addTextInput(String name) {
		JPanel container = makeContainer();
		panel.add(container);

		JTextField text = new JTextField();
		text.setPreferredSize(new Dimension(252, 30));

		JLabel label = new JLabel(" " + name + " :");
		label.setPreferredSize(new Dimension(170, 30));
		label.setBorder(BorderFactory.createLineBorder(dark));
		label.setForeground(dark);

		JPanel padding = new JPanel();
		padding.setPreferredSize(new Dimension(150, 30));
		padding.setBackground(light);

		container.add(label);
		container.add(text);
		container.add(padding);
		return text;
	}

	private void addLaunchButton() {
		JPanel container = makeContainer();
		container.setPreferredSize(new Dimension(600, 50));
		panel.add(container);

		JButton launch = new JButton("Estimate");
		launch.setIcon(new ImageIcon("estimate.png"));
		launch.setBackground(light);
		launch.setForeground(dark);
		launch.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				Project newProject = new Project();

				for (String s : properties.keySet()) {

					if (properties.get(s).getSelection() != null) {
						newProject.addCharacteristic(new ProjectProperty(s,
								properties.get(s).getSelection()
										.getActionCommand()));
					}
				}

				// try {
				// Double.parseDouble(effortInput.getText());
				// p.addCharacteristic(new
				// ProjectProperty("ACT_EFFORT",effortInput.getText()));
				// } catch (NumberFormatException numberError){
				// JOptionPane.showMessageDialog(CompareWindow.this,
				// "Could not parse \"" +effortInput.getText() + "\"" );
				// return;
				// }
				//	
				if (!locInput.getText().equals("")) {
					try {
						Double.parseDouble(locInput.getText());
						newProject.addCharacteristic(new ProjectProperty("LOC",
								locInput.getText()));
					} catch (NumberFormatException numberError) {
						JOptionPane.showMessageDialog(CompareWindow.this,
								"Could not parse \"" + locInput.getText()
										+ "\" as a number. Please write numbers with the format ##.##, for example \"12.85\" or \"30\"");
						return;
					}
				} else {
					JOptionPane.showMessageDialog(CompareWindow.this,"You have to enter a value in \"KLOC\". Please do so before estimating!");
					return;
				}

				// Logger.log("Here I should compare " +
				// String.valueOf(p)+" with " + String.valueOf(oldProjects));

				double totalSimilarity = 0;
				double thresh = ThresholdPrefs.get(50) / 100.0;
				ArrayList<Project> filteredProjects = new ArrayList<Project>();

	
				HashMap<String, Double> ranges = new HashMap<String, Double>();

				ranges = Ranges.calculateUsing(characteristics, oldProjects,
						newProject);

				for (int i = 0; i < oldProjects.size(); i++) {
					Project pr = oldProjects.get(i);

					double sim = Similarity.compare(pr, newProject, ranges);

					if (sim >= thresh) {
						totalSimilarity += sim;
						filteredProjects.add(pr);
					}
				}

				double effort = 0;
				
				
				
				if(projectType.getSelection() == null){
					JOptionPane.showMessageDialog(CompareWindow.this,"You have to specify a type of project. Please do so before estimating!");
					return;
				} 
				String constants = projectType.getSelection().getActionCommand();
				
				for (Project pr : filteredProjects) {
//					effort += (pr.getCharacteristic("ACT_EFFORT").getValue()
//							* newProject.getCharacteristic("LOC").getValue() / pr
//							.getCharacteristic("LOC").getValue())
//							* (Similarity.compare(pr, newProject, ranges))
//							/ totalSimilarity;
					
					if (totalSimilarity == 0) {
						effort += Cocomo.effort(constants, newProject.getCharacteristic("LOC").getValue(), newProject.getEAF()) / filteredProjects.size();
					} else  {
						effort += Cocomo.effort(constants, newProject.getCharacteristic("LOC").getValue(), newProject.getEAF())
							* (Similarity.compare(pr, newProject, ranges))
							/ totalSimilarity;
					}
				}
				// Logger.log("The estimated effort is " + effort
				// +". Calculated using " + filteredProjects.size()
				// +" old projects with an average similarity of " +
				// totalSimilarity/filteredProjects.size());

				DecimalFormat twoDForm = new DecimalFormat("#.##");
				Logger.log(effort +"");
				double roundedEffort = Double.valueOf(twoDForm.format(effort));

				StringBuilder sb = new StringBuilder();
				// sb.append("The projects used in the comparison had an average similarity of "
				// + roundedAvg +". ");
				sb.append("<html>");
				if (filteredProjects.size() == 0) {
					sb
							.append("Unable to calculate the estimated effort. There are no projects similar enough to be used in the comparison. Please lower the threshold.");
				} else {
					double roundedAvg = Double.valueOf(twoDForm
							.format(totalSimilarity / filteredProjects.size()));

					// sb.append("The estimated effort is <b>" + effort
					// +"</b>. It was calculated using " +
					// filteredProjects.size() +" of your old projects. ");
					int roundedYear = (int) (roundedEffort/12);
					int roundedMonth = (int) (roundedEffort%12);
					int roundedDay = (int) ((roundedEffort-roundedMonth-roundedYear*12)*19);
					int roundedHour = (int) ((roundedEffort-roundedMonth-roundedYear*12-roundedDay/19.0)*152);

					sb
							.append("Estimated effort is <strong>"
									+ roundedYear + "</strong> person-years,<strong> " + roundedMonth + " </strong>person-months,<strong> " +  roundedDay +" </strong>person-days and <strong>" + roundedHour + " </strong>person-hours <strong>"  
									+ "</strong>.<br><br>This was calculated using <strong>"
									+ filteredProjects.size()
									+ "</strong> projects"
									+ " with an average similarity of <strong>"
									+ roundedAvg + "</strong>.");

					if ((oldProjects.size() / filteredProjects.size()) >= 10)
						sb
								.append("<br><br>Perhaps to few projects were used in the comparison. Please consider using a lower treshold. ");
					else if (roundedAvg <= 0.6)
						sb
								.append("<br><br>Perhaps to many projects were used in the comparison. Please consider using a higher treshold. ");

				}
				sb.append("</html>");
				JLabel label = new JLabel(sb.toString());
				label.setFont(new Font("serif", Font.PLAIN, 14));
				// JOptionPane.showMessageDialog(null, label);
				JOptionPane.showMessageDialog(null, label, "Result",
						JOptionPane.INFORMATION_MESSAGE);
				// JOptionPane.showMessageDialog(null, sb.toString());

			}
		});

		container.add(launch);
	}

	private void addLowHighSelection(String name, ArrayList<String> allowedValue) {
		JPanel container = makeContainer();
		panel.add(container);

		ButtonGroup radio = new ButtonGroup();
		properties.put(name, radio);

		JRadioButton veryLow = makeRadio("Very_Low", allowedValue);
		JRadioButton low = makeRadio("Low", allowedValue);
		JRadioButton medium = makeRadio("Nominal", allowedValue);
		JRadioButton high = makeRadio("High", allowedValue);
		JRadioButton veryHigh = makeRadio("Very_High", allowedValue);
		JRadioButton extraHigh = makeRadio("Extra_High", allowedValue);
		veryLow.setBackground(light);
		low.setBackground(light);
		medium.setBackground(light);
		high.setBackground(light);
		veryHigh.setBackground(light);
		extraHigh.setBackground(light);
		radio.add(veryLow);
		radio.add(low);
		radio.add(medium);
		radio.add(high);
		radio.add(veryHigh);
		radio.add(extraHigh);

		JLabel label = new JLabel(" " + name + " :");
		label.setForeground(dark);
		label.setPreferredSize(new Dimension(170, 30));
		label.setBorder(BorderFactory.createLineBorder(dark));
		container.add(label);

		container.add(veryLow);
		container.add(low);
		container.add(medium);
		container.add(high);
		container.add(veryHigh);
		container.add(extraHigh);

		final JLabel chosen = new JLabel("");
		chosen.setPreferredSize(new Dimension(150, 30));
		container.add(chosen);

		ActionListener chooseAction = new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				JRadioButton b = (JRadioButton) arg0.getSource();
				chosen.setText(b.getActionCommand());
			}
		};

		veryLow.addActionListener(chooseAction);
		low.addActionListener(chooseAction);
		medium.addActionListener(chooseAction);
		high.addActionListener(chooseAction);
		veryHigh.addActionListener(chooseAction);
		extraHigh.addActionListener(chooseAction);
	}

	private JRadioButton makeRadio(String string, ArrayList<String> allowedValue) {
		ImageIcon closed = load("banana_closed.jpg", 30, 30);
		ImageIcon open = load("banana_open.jpg", 30, 30);

		JRadioButton button = new JRadioButton();

		button.setIcon(closed);
		button.setPressedIcon(open);
		button.setSelectedIcon(open);

		button.setActionCommand(string);

		if (!allowedValue.contains(string)) {

			button.setEnabled(false);
		}
		return button;
	}
	
	private JRadioButton makeRadio(String string) {
		ImageIcon closed = load("banana_closed.jpg", 30, 30);
		ImageIcon open = load("banana_open.jpg", 30, 30);

		JRadioButton button = new JRadioButton();

		button.setIcon(closed);
		button.setPressedIcon(open);
		button.setSelectedIcon(open);

		button.setActionCommand(string);

		return button;
	}
	private ImageIcon load(String file, int w, int h) {
		ImageIcon ii = new ImageIcon(file);

		int type = BufferedImage.TYPE_INT_RGB;
		BufferedImage dst = new BufferedImage(w, h, type);
		Graphics2D g2 = dst.createGraphics();
		g2.drawImage(ii.getImage(), 0, 0, w, h, this);
		g2.dispose();
		return new ImageIcon(dst);
	}
}
